#include "utils/PMIHelper.h"
#include "pmi/ExchangeDimension.h"
#include "pmi/ExchangeGDT.h"
#include "pmi/ExchangePMIBase.h"
#include "pmi/ExchangePMIDatum.h"
#include "pmi/ExchangePMINote.h"
#include "pmi/ExchangePMINote.h"
#include "pmi/ExchangeRoughness.h"
#include "pmi/InterOpDimension.h"
#include "pmi/InterOpGDT.h"
#include "pmi/InterOpPMIBase.h"
#include "pmi/InterOpPMIDatum.h"
#include "pmi/InterOpPMINote.h"
#include "pmi/InterOpRoughness.h"
#include <memory>
#define CONCAT2(a, b) a##b
#define MAKE_ENUM_NAME(name) CONCAT2( , name)
#define CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(type) \
    case InterOp::PMI::MAKE_ENUM_NAME(type) : \
        result = Core::PMI::MAKE_ENUM_NAME(type) ; \
        break ; 
        

AMCAX_EXCHANGE_NAMESPACE_BEGIN

namespace PMIHelper{

// PMIDimensionMainType 
Core::PMI::PMIDimensionMainType ToExchangePMIDimensionMainType(InterOp::PMI::PMIDimensionMainType type)
{
    Core::PMI::PMIDimensionMainType result = Core::PMI::PMIDimensionMainType::DMT_Unknown;
    switch (type)
    {
    CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionMainType::DMT_Basic) ;
    CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionMainType::DMT_Reference) ; 
	CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionMainType::DMT_Tolerance ) ;
	CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionMainType::DMT_CoordDim	) ;
	CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionMainType::DMT_HoleCallout ) ;
    
    default:
        break;
    }
#if 0
    switch (type)
    {
    case InterOp::PMI::PMIDimensionMainType::DMT_Basic :
        result = Core::PMI::PMIDimensionMainType::DMT_Basic ;
        break;
    case InterOp::PMI::PMIDimensionMainType::DMT_Reference :
        result = Core::PMI::PMIDimensionMainType::DMT_Reference ;
        break;
    case InterOp::PMI::PMIDimensionMainType::DMT_Tolerance :
        result = Core::PMI::PMIDimensionMainType::DMT_Tolerance ;
        break;
    case InterOp::PMI::PMIDimensionMainType::DMT_CoordDim :
        result = Core::PMI::PMIDimensionMainType:: DMT_CoordDim;
        break;
    case InterOp::PMI::PMIDimensionMainType::DMT_HoleCallout :
        result = Core::PMI::PMIDimensionMainType::DMT_HoleCallout ;
        break;
    
    default:
        break;
    }
#endif
    return result ;
}

Core::PMI::PMIDimensionSubType ToExchangePMIDimensionSubType(InterOp::PMI::PMIDimensionSubType type)
{
    Core::PMI::PMIDimensionSubType result = Core::PMI::PMIDimensionSubType::UNKNOWN;
    
    switch (type)
    {
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::Distance) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::DistanceOffset) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::Length) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::Length_OR_Distance) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::LengthCurvilinear) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::Angle) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::Radius) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::RadiusTangent) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::RadiusCylinder) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::RadiusEdge) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::Diameter) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::DiameterTangent) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::DiameterCylinder) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::DiameterEdge) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::DiameterCone) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::Chamfer) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::Slope) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::DimGDT) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::DimDatumFeature) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::DimDatumTarget) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::DimBalloon) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::No_Dim) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::AngleArc) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::LengthCircular) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::Fillet) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::CoordDimension_2D) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionSubType::CoordDimension_3D) ;
#if 0
    case InterOp::PMI::PMIDimensionSubType::Distance :
        result = Core::PMI::PMIDimensionSubType::Distance ;
        break;
    case InterOp::PMI::PMIDimensionSubType::DistanceOffset :
        result = Core::PMI::PMIDimensionSubType::DistanceOffset ;
        break;
    case InterOp::PMI::PMIDimensionSubType::Length :
        result = Core::PMI::PMIDimensionSubType::Length ;
        break;
    case InterOp::PMI::PMIDimensionSubType::Length_OR_Distance :
        result = Core::PMI::PMIDimensionSubType::Length_OR_Distance ;
        break;
    case InterOp::PMI::PMIDimensionSubType::LengthCurvilinear :
        result = Core::PMI::PMIDimensionSubType::LengthCurvilinear ;
        break;
    case InterOp::PMI::PMIDimensionSubType::Angle :
        result = Core::PMI::PMIDimensionSubType::Angle ;
        break;
    case InterOp::PMI::PMIDimensionSubType::Radius :
        result = Core::PMI::PMIDimensionSubType::Radius ;
        break;
    case InterOp::PMI::PMIDimensionSubType::RadiusTangent :
        result = Core::PMI::PMIDimensionSubType::RadiusTangent ;
        break;
    case InterOp::PMI::PMIDimensionSubType::RadiusCylinder :
        result = Core::PMI::PMIDimensionSubType::RadiusCylinder ;
        break;
    case InterOp::PMI::PMIDimensionSubType::RadiusEdge :
        result = Core::PMI::PMIDimensionSubType::RadiusEdge ;
        break;
    case InterOp::PMI::PMIDimensionSubType::Diameter :
        result = Core::PMI::PMIDimensionSubType::Diameter ;
        break;
    case InterOp::PMI::PMIDimensionSubType::DiameterTangent :
        result = Core::PMI::PMIDimensionSubType::DiameterTangent ;
        break;
    case InterOp::PMI::PMIDimensionSubType::DiameterCylinder :
        result = Core::PMI::PMIDimensionSubType::DiameterCylinder ;
        break;
    case InterOp::PMI::PMIDimensionSubType::DiameterEdge :
        result = Core::PMI::PMIDimensionSubType::DiameterEdge ;
        break;
    case InterOp::PMI::PMIDimensionSubType::DiameterCone :
        result = Core::PMI::PMIDimensionSubType::DiameterCone ;
        break;
    case InterOp::PMI::PMIDimensionSubType::Chamfer :
        result = Core::PMI::PMIDimensionSubType::Chamfer ;
        break;
    case InterOp::PMI::PMIDimensionSubType::Slope :
        result = Core::PMI::PMIDimensionSubType::Slope ;
        break;
    case InterOp::PMI::PMIDimensionSubType::DimGDT :
        result = Core::PMI::PMIDimensionSubType::DimGDT ;
        break;
    case InterOp::PMI::PMIDimensionSubType::DimDatumFeature :
        result = Core::PMI::PMIDimensionSubType::DimDatumFeature ;
        break;
    case InterOp::PMI::PMIDimensionSubType::DimDatumTarget :
        result = Core::PMI::PMIDimensionSubType::DimDatumTarget ;
        break;
    case InterOp::PMI::PMIDimensionSubType::DimBalloon :
        result = Core::PMI::PMIDimensionSubType::DimBalloon ;
        break;
    case InterOp::PMI::PMIDimensionSubType::No_Dim :
        result = Core::PMI::PMIDimensionSubType::No_Dim ;
        break;
    case InterOp::PMI::PMIDimensionSubType::AngleArc :
        result = Core::PMI::PMIDimensionSubType::AngleArc ;
        break;
    case InterOp::PMI::PMIDimensionSubType::LengthCircular :
        result = Core::PMI::PMIDimensionSubType::LengthCircular ;
        break;
    case InterOp::PMI::PMIDimensionSubType::Fillet :
        result = Core::PMI::PMIDimensionSubType::Fillet ;
        break;
    case InterOp::PMI::PMIDimensionSubType::CoordDimension_2D :
        result = Core::PMI::PMIDimensionSubType::CoordDimension_2D ;
        break;
    case InterOp::PMI::PMIDimensionSubType::CoordDimension_3D :
        result = Core::PMI::PMIDimensionSubType::CoordDimension_3D ;
        break;
#endif
    default:
        break;
    }

    return result ;
}

Core::PMI::PMIUnit ToExchangePMIUnit(InterOp::PMI::PMIUnit type)
{
    Core::PMI::PMIUnit result = Core::PMI::PMIUnit::DimUnitNone;
    
    switch (type)
    {
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIUnit::DimUnitNone) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIUnit::DimUnitMM) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIUnit::DimUnitINCH) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIUnit::DimUnitMETER) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIUnit::DimUnitCM) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIUnit::DimUnitKM) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIUnit::DimUnitFOOT) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIUnit::DimUnitF_I_F64) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIUnit::DimUnitF_I_F16) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIUnit::DimUnitF_I_DEC) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIUnit::DimUnitDEGREE) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIUnit::DimUnitMINUTE) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIUnit::DimUnitSECOND) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIUnit::DimUnitRADIAN) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIUnit::DimUnitGRADE) ;
    default:
        break;
    }

    return result ;
}

Core::PMI::PMIDimensionFakeType ToExchangePMIDimensionFakeType(InterOp::PMI::PMIDimensionFakeType type)
{
    Core::PMI::PMIDimensionFakeType  result = Core::PMI::PMIDimensionFakeType::FakeUnknown;
    
    switch (type)
    {
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionFakeType::FakeUnknown) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionFakeType::FakeNumeric) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDimensionFakeType::FakeText) ;
    
    default:
        break;
    }   
    return result ;
}

Core::PMI::PMIArrowSymbol ToExchangePMIArrowSymbol(InterOp::PMI::PMIArrowSymbol type)
{
    Core::PMI::PMIArrowSymbol  result = Core::PMI::PMIArrowSymbol::NOTUSED;
    
    switch (type)
    {
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::NOTUSED) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::CROSS) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::PLUS) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::CONCENTRIC) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::COINCIDENT) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::FULLCIRCLE) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::FULLSQUARE) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::STAR) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::DOT) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::SMALLDOT) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::MISC1) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::MISC2) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::FULLCIRCLE2) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::FULLSQUARE2) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::OPEN_ARROW) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::UNFILLED_ARROW) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::BLANKED_ARROW) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::FILLED_ARROW) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::UNFILLED_CIRCLE) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::BLANKED_CIRCLE) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::FILLED_CIRCLE) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::CROSSED_CIRCLE) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::BLANKED_SQUARE) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::FILLED_SQUARE) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::BLANKED_TRIANGLE) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::FILLED_TRIANGLE) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::MANIPULATOR_SQUARE) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::MANIPULATOR_DIAMOND) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::MANIPULATOR_CIRCLE) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::MANIPULATOR_TRIANGLE) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::DOUBLE_OPEN_ARROW) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIArrowSymbol::WAVE) ;
    
    default:
        break;
    }   
    return result ;
}

Core::PMI::PMICalloutFeatureAnnotationType ToExchangePMICalloutFeatureAnnotationType(InterOp::PMI::PMICalloutFeatureAnnotationType type)
{
    Core::PMI::PMICalloutFeatureAnnotationType  result = Core::PMI::PMICalloutFeatureAnnotationType::FEATURETYPE_UNKNOWN;
    
    switch (type)
    {
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMICalloutFeatureAnnotationType::FEATURETYPE_HOLE_UNKNOWN) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTFIT) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTDEPTH) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTDIAMETER) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTSCREWSIZE) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTCOUNTERBOREDEPTH) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTCOUNTERBOREDIAMETER) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTPATTERNCOUNT) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTPITCH) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTANGLE) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTPATTAPERANGLE) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTCOUNTERSINKDIAMETER) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTPATCOUNTERSINKANGLE) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTTHREADDEPTH) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTTHREADSIZE) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTTHREADMINORDIA) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTTHREADMAJORDIA) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTTAPDRILLDIA) ;		
    
    default:
        break;
    }   
    return result ;
}

Core::PMI::PMIToleranceType ToExchangePMIToleranceType(InterOp::PMI::PMIToleranceType type)
{
    Core::PMI::PMIToleranceType  result = Core::PMI::PMIToleranceType::UNKNOWN;
    
    switch (type)
    {
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceType::Form_Straightness) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceType::Form_Flatness) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceType::Form_Circularity) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceType::Form_Cylindricity) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceType::Form_ProfileAnyLine) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceType::Form_ProfileAnySurface) ;

	// Orientation tolerance
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceType::Orientation_Parallelism) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceType::Orientation_Perpendicularity) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceType::Orientation_Angularity) ;
											  /**<  */
	// Position tolerance
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceType::Location_TruePosition) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceType::Location_Concentricity) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceType::Location_Coaxiality) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceType::Location_Symmetry) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceType::Location_PositionOfAnyLine) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceType::Location_PositionOfASurface) ;

	// Run-out tolerance
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceType::RunOut_Circular) ;
	    CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceType::RunOut_Total) ;
    
    default:
        break;
    }   
    return result ;
}

Core::PMI::PMIToleranceValueType ToExchangePMIToleranceValueType(InterOp::PMI::PMIToleranceValueType type)
{
    Core::PMI::PMIToleranceValueType  result = Core::PMI::PMIToleranceValueType::NONE;
    
    switch (type)
    {
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceValueType::DIAMETER) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceValueType::RADIUS) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceValueType::SPHERICAL) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceValueType::SQUARE) ;
    
    default:
        break;
    }   
    return result ;
}

Core::PMI::PMIToleranceModifierType ToExchangePMIToleranceModifierType(InterOp::PMI::PMIToleranceModifierType type)
{
    Core::PMI::PMIToleranceModifierType  result = Core::PMI::PMIToleranceModifierType::NoModifier;
    
    switch (type)
    {
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::MaterialCondition_Unsupported) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::MaterialCondition_NoModifier) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::MaterialCondition_Maximum) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::MaterialCondition_Least) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::MaterialCondition_RegardlessOfFeatureSize) ;

        // Tangent planes
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::TangentPlane_Unsupported) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::TangentPlane_NotTangent) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::TangentPlane_Tangent) ;

        // Free State
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::FreeState_Unsupported) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::FreeState_Free) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::FreeState_NotFree) ;

        //ST symbol
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::Statistical_Symbol) ;

        //Common Zone
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::CommonZone) ;


        //Unequally Disposed Tolerance Zone
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::UnequallyDisposedZone) ;

        // Projected State
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::ProjectedState_Projected) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::ProjectedState_NotProjected) ;

        // Circle U 
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::CircleU) ;

        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::Maximum) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::MinimaxFeature) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::DerivedFeature) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::DynamicProfile) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::LeastSquareFeature) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::MaximumInscribedFeature) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::MinimumCircumscribedFeature) ;

        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::SeparateZone) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::OffsetZone) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::VariableAngle) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::OrientationConstraint) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::MinimaxAssociation) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::MinimaxAssociationWithExternalConstraint) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::MinimaxAssociationWithInternalConstraint) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::LeastSquareAssociation) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::LeastSquareAssociationWithExternalConstraint) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::LeastSquareAssociationWithInternalConstraint) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::MinimumCircumscribedAssociation) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::MaximumInscribedAssociation) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::TotalRangeOfDeviations) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::PeakHeight) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::ValleyDepth) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIToleranceModifierType::StandardDeviation) ;
    
    default:
        break;
    }   
    return result ;
}

Core::PMI::PMIDatumTargetType ToExchangePMIDatumTargetType(InterOp::PMI::PMIDatumTargetType type)
{
    Core::PMI::PMIDatumTargetType  result = Core::PMI::PMIDatumTargetType::Unknown;
    
    switch (type)
    {
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDatumTargetType::Point)
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDatumTargetType::Line)
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDatumTargetType::AreaCircular)
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDatumTargetType::AreaRectangular)
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDatumTargetType::AreaFace)
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDatumTargetType::Feature)
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIDatumTargetType::UserDefined)
    
    default:
        break;
    }   
    return result ;
}

Core::PMI::PMIFont ToExchangePMIFont(InterOp::PMI::PMIFont type)
{
    Core::PMI::PMIFont  result  ;
    
    switch (type)
    {
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIFont::Simplex) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIFont::Din) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIFont::Military) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIFont::ISO) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIFont::Lightline) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIFont::Century) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIFont::IGES_1001) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIFont::IGES_1002) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIFont::IGES_1003) ;
    
    default:
        break;
    }   
    return result ;
}


Core::PMI::PMIRoughnessApplicabilityType ToExchangePMIRoughnessApplicabilityType(InterOp::PMI::PMIRoughnessApplicabilityType type)
{
    Core::PMI::PMIRoughnessApplicabilityType  result = Core::PMI::PMIRoughnessApplicabilityType::UnSupported ;
    
    switch (type)
    {
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIRoughnessApplicabilityType::SpecifiedSurfaceOnly) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIRoughnessApplicabilityType::AllPartSurfaces) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIRoughnessApplicabilityType::BasicSurface) ;
    
    default:
        break;
    }   
    return result ;
}

Core::PMI::PMIRoughnessObtentionType ToExchangePMIRoughnessObtentionType(InterOp::PMI::PMIRoughnessObtentionType type)
{
    Core::PMI::PMIRoughnessObtentionType  result = Core::PMI::PMIRoughnessObtentionType::UnSupported ;
    
    switch (type)
    {
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIRoughnessObtentionType::NotDefined) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIRoughnessObtentionType::MachiningMandatory) ;
        CAST_INTEROP_ENUM_TO_EXCHANGE_ENUM(PMIRoughnessObtentionType::MachiningForbidden) ;
    
    default:
        break;
    }   
    return result ;
}

std::shared_ptr<Core::PMI::ExchangePMIAnnotation>  ToExchangePMIDimension(const std::shared_ptr<InterOp::PMI::InterOpPMIAnnotation> & base)
{
    std::shared_ptr<InterOp::PMI::InterOpPMIDimension> annotation = Cast_InterOpPMIDimension(base) ;
    if (!annotation)
    {
        return nullptr ;
    }
    
    
    std::shared_ptr<AMCAX::Exchange::Core::PMI::ExchangePMIDimension> result = std::make_shared<Core::PMI::ExchangePMIDimension>() ;
    result->SetId(annotation->GetId()) ;
    result->SetIsHide(annotation->GetIsHide()) ;
    result->SetName(annotation->GetName()) ;
    result->SetMainType(ToExchangePMIDimensionMainType(annotation->GetMainType())) ;
    result->SetSubType(ToExchangePMIDimensionSubType(annotation->GetSubType())) ;
    result->SetCalloutFeatureAnnotationType(ToExchangePMICalloutFeatureAnnotationType(annotation->GetCalloutFeatureAnnotationType())) ;
    result->SetIsDriving(annotation->GetIsDriving()) ;
    result->SetCoordValue(annotation->GetCoordValue()[0],annotation->GetCoordValue()[1],annotation->GetCoordValue()[2]) ;
    result->SetDimensionValue(annotation->GetDimensionValue()) ;
    result->SetUnit(ToExchangePMIUnit(annotation->GetUnit())) ;
    result->SetTolerancePrecisionValue(annotation->GetTolerancePrecisionValue()) ;
    result->SetToleranceNumerialLowerValue(annotation->GetToleranceNumerialLowerValue())  ;
    result->SetToleranceNumerialUpperValue(annotation->GetToleranceNumerialUpperValue())  ;
    result->SetToleranceAlphanumericalLowerValue(annotation->GetToleranceAlphanumericalLowerValue()) ;
    result->SetToleranceAlphanumericalUpperValue(annotation->GetToleranceAlphanumericalUpperValue()) ;
    result->SetNumbericalFakeValue(annotation->GetNumbericalFakeValue())  ;
    result->SetAlphanumericalFakeValue(annotation->GetAlphanumericalFakeValue()) ;
    InterOp::PMI::InterOpPMIText text = annotation->GetNote() ;
    Core::PMI::ExchangePMIText exchangeNote ;
    
    exchangeNote.SetUpperText(text.GetUpperText()) ;
    
    exchangeNote.SetLowerText(text.GetLowerText()) ;
    
    exchangeNote.SetBeforeText(text.GetBeforeText()) ;
    
    exchangeNote.SetAfterText(text.GetAfterText()) ;
    
    exchangeNote.SetPrefixText(text.GetPrefixText()) ;
    
    exchangeNote.SetSuffixText(text.GetSuffixText()) ;
    
    exchangeNote.SetBelowText(text.GetBelowText()) ;
    result->SetNote(exchangeNote) ;
    
    result->SetLine2dStart(annotation->GetLine2dStart()[0],annotation->GetLine2dStart()[1]) ;
    
    result->SetLine2dEnd(annotation->GetLine2dEnd()[0], annotation->GetLine2dEnd()[1]) ;
    result->SetLine2dSymbolStart(ToExchangePMIArrowSymbol(annotation->GetLine2dSymbolStart())) ;
    result->SetLine2dSymbolEnd(ToExchangePMIArrowSymbol(annotation->GetLine2dSymbolEnd())) ;
    return result ;
}

std::shared_ptr<Core::PMI::ExchangePMIAnnotation>  ToExchangeGDT(const std::shared_ptr<InterOp::PMI::InterOpPMIAnnotation> & base)
{
    std::shared_ptr<InterOp::PMI::InterOpGDT> annotation = Cast_InterOpGDT(base) ;
    std::shared_ptr<AMCAX::Exchange::Core::PMI::ExchangeGDT> result = std::make_shared<Core::PMI::ExchangeGDT>() ;

    result->SetId(annotation->GetId()) ;
    result->SetName(annotation->GetName()) ;	
    result->SetIsHide(annotation->GetIsHide()) ;
    result->SetToleranceType(ToExchangePMIToleranceType(annotation->GetToleranceType())) ;
    result->SetToleranceValueType(ToExchangePMIToleranceValueType(annotation->GetToleranceValueType()) ) ;
    result->SetRefinementToleranceValue(annotation->GetRefinementToleranceValue()) ;
    result->SetRateUnit1(annotation->GetRateUnit1()) ;
    result->SetRateUnit2(annotation->GetRateUnit2()) ;
    result->SetProjectedToleranceLength(annotation->GetProjectedToleranceLength()) ;
    result->SetProfileShiftValue(annotation->GetProfileShiftValue()) ;
    result->SetAllAround(annotation->GetAllAround()) ;
    result->SetNote(annotation->GetNote()) ;
    
    InterOp::PMI::InterOpPMIText text = annotation->GetNoteText() ;
    Core::PMI::ExchangePMIText exchangeNote ;
    
    exchangeNote.SetUpperText(text.GetUpperText()) ;
    
    exchangeNote.SetLowerText(text.GetLowerText()) ;
    
    exchangeNote.SetBeforeText(text.GetBeforeText()) ;
    
    exchangeNote.SetAfterText(text.GetAfterText()) ;
    
    exchangeNote.SetPrefixText(text.GetPrefixText()) ;
    
    exchangeNote.SetSuffixText(text.GetSuffixText()) ;
    
    exchangeNote.SetBelowText(text.GetBelowText()) ;
    result->SetNoteText(exchangeNote) ;
    
    for(auto &r : annotation->GetGDTRows()){
        Core::PMI::ExchangeGDTRow row ;

        row.SetToleranceValue(r.GetToleranceValue()) ;
        row.SetToleranceValueType(ToExchangePMIToleranceValueType(r.GetToleranceValueType())) ;
        row.SetRefinementToleranceValue(r.GetRefinementToleranceValue()) ;
        row.SetRateUnit1(r.GetRateUnit1()) ;
        row.SetRateUnit2(r.GetRateUnit2()) ;
        for(auto m : r.GetZoneModifiers()){
            Core::PMI::PMIZoneModifier  modifier ;
            
            modifier.SetZoneModifierMagnitudeValue(m.GetZoneModifierMagnitudeValue()) ;
            modifier.SetZoneModifierType(ToExchangePMIToleranceModifierType(m.GetZoneModifierType())) ;
            
            row.AddZoneModifier(modifier) ;
        }

        auto refFrame = r.GetGDTRefFrame() ;
        if(refFrame){
            std::shared_ptr<Core::PMI::GDTRefFrame> exchangeRefFrame = std::make_shared<Core::PMI::GDTRefFrame>() ;

            exchangeRefFrame->SetLabel(refFrame->GetLabel()) ;
            
            for(auto interOpRef : refFrame->GetDatumRefs()){
                std::shared_ptr<Core::PMI::DatumRef> ref ;
                ref->SetLabel(interOpRef->GetLabel()) ;
                InterOp::PMI::InterOpPMIText tempText = interOpRef->GetText() ;
                Core::PMI::ExchangePMIText exchangeTempText ;
                exchangeTempText.SetUpperText(tempText.GetUpperText()) ;
    
                exchangeTempText.SetLowerText(tempText.GetLowerText()) ;
                
                exchangeTempText.SetBeforeText(tempText.GetBeforeText()) ;
                
                exchangeTempText.SetAfterText(tempText.GetAfterText()) ;
                
                exchangeTempText.SetPrefixText(tempText.GetPrefixText()) ;
                
                exchangeTempText.SetSuffixText(tempText.GetSuffixText()) ;
                
                exchangeTempText.SetBelowText(tempText.GetBelowText()) ;
                ref->SetText(exchangeTempText) ;

                for(auto interOpModifiedDatum : interOpRef->GetModifierDatums()){
                    Core::PMI::PMIModifiedDatum exchangeModifiedDatum ;
                    for(auto interOpZoneModifier : interOpModifiedDatum.GetZoneModifiers()){
                        Core::PMI::PMIZoneModifier exchangeZoneModifier ;
                        exchangeZoneModifier.SetZoneModifierType(ToExchangePMIToleranceModifierType(interOpZoneModifier.GetZoneModifierType())) ;
                        exchangeZoneModifier.SetZoneModifierMagnitudeValue(interOpZoneModifier.GetZoneModifierMagnitudeValue()) ;
                        exchangeModifiedDatum.AddZoneModifier(exchangeZoneModifier) ;
                    }
                    ref->AddModifierDatum(exchangeModifiedDatum) ;
                }


                exchangeRefFrame->AddDatumRef(ref) ;
            }

            row.SetGDTRefFrame(exchangeRefFrame) ;
        }

        result->AddGDTRow(row); 
    }

    return result ;
}

std::shared_ptr<Core::PMI::ExchangePMIAnnotation>  ToExchangePMIDatumTarget(const std::shared_ptr<InterOp::PMI::InterOpPMIAnnotation> & base)
{
    std::shared_ptr<InterOp::PMI::InterOpPMIDatumTarget> annotation = Cast_InterOpPMIDatumTarget(base) ;
    // TODO:
    std::shared_ptr<AMCAX::Exchange::Core::PMI::ExchangePMIDatumTarget> result = std::make_shared<Core::PMI::ExchangePMIDatumTarget>() ;
    return result ;
}

std::shared_ptr<Core::PMI::ExchangePMIAnnotation>  ToExchangeDatum(const std::shared_ptr<InterOp::PMI::InterOpPMIAnnotation> & base)
{
    std::shared_ptr<InterOp::PMI::PMIInterOpDatum> annotation = Cast_PMIInterOpDatum(base) ;
    std::shared_ptr<AMCAX::Exchange::Core::PMI::PMIExchangeDatum> result = std::make_shared<Core::PMI::PMIExchangeDatum>() ;
    result->SetId(annotation->GetId()) ;
    result->SetName(annotation->GetName()) ;
    result->SetIsHide(annotation->GetIsHide()) ;
    result->SetLabel(annotation->GetLabel()) ;
    
    for(auto t : annotation->GetDatumTargets())
    {
        auto exchangeDatumTarget = std::make_shared<Core::PMI::ExchangePMIDatumTarget>() ;
        exchangeDatumTarget->SetLabel(t->GetLabel()) ;
        exchangeDatumTarget->SetTargetType(ToExchangePMIDatumTargetType(t->GetTargetType())) ;
        exchangeDatumTarget->SetHasDiameter(t->GetHasDiameter()) ;
        exchangeDatumTarget->SetUpperText(t->GetUpperText()) ;
        exchangeDatumTarget->SetLowerText(t->GetLowerText()) ;
        exchangeDatumTarget->SetPosition1(t->GetPosition1()[0],t->GetPosition1()[1],t->GetPosition1()[2]) ;
        exchangeDatumTarget->SetPosition2(t->GetPosition2()[0],t->GetPosition2()[1],t->GetPosition2()[2]) ;
        result->AddDatumTarget(exchangeDatumTarget) ;
    }
    return result ;
}

std::shared_ptr<Core::PMI::ExchangePMIAnnotation>  ToExchangePMINote(const std::shared_ptr<InterOp::PMI::InterOpPMIAnnotation> & base)
{
    std::shared_ptr<InterOp::PMI::InterOpNote> annotation = Cast_InterOpNote(base) ;
    std::shared_ptr<AMCAX::Exchange::Core::PMI::ExchangeNote> result = std::make_shared<Core::PMI::ExchangeNote>() ;

    result->SetId(annotation->GetId()) ;
    result->SetName(annotation->GetName()) ;
    result->SetIsHide(annotation->GetIsHide()) ;
    result->SetIsFlagNote(annotation->GetIsFlagNote())  ;
    result->SetIsNOA(annotation->GetIsNOA()) ;
    for(auto t: annotation->GetNoteTexts())
    {
        Core::PMI::ExchangeNote::Text exchangeText ;
        exchangeText.label = t.label  ;
        exchangeText.fontName = t.fontName  ;
        exchangeText.fontType = ToExchangePMIFont(t.fontType)  ;
        exchangeText.fixedPitch = t.fixedPitch  ;
        exchangeText.height = t.height  ;
        exchangeText.bold = t.bold  ;
        exchangeText.italic = t.italic  ;
        exchangeText.underline = t.underline  ;
        exchangeText.strikeThrough = t.strikeThrough  ;
        exchangeText.overline = t.overline  ;
        exchangeText.ratio = t.ratio  ;
        exchangeText.slant = t.slant  ;
        exchangeText.rgbaColor[0] = t.rgbaColor[0]  ;
        exchangeText.rgbaColor[1] = t.rgbaColor[1]  ;
        exchangeText.rgbaColor[2] = t.rgbaColor[2]  ;
        exchangeText.rgbaColor[3] = t.rgbaColor[3]  ;
        result->AddText(exchangeText) ;
    }
    return result ;
}

std::shared_ptr<Core::PMI::ExchangePMIAnnotation>  ToExchangePMIRoughness(const std::shared_ptr<InterOp::PMI::InterOpPMIAnnotation> & base)
{
    std::shared_ptr<InterOp::PMI::InterOpRoughness> annotation = Cast_InterOpRoughness(base) ;
    std::shared_ptr<AMCAX::Exchange::Core::PMI::ExchangeRoughness> result = std::make_shared<Core::PMI::ExchangeRoughness>() ;

    result->SetId(annotation->GetId()) ;
    result->SetName(annotation->GetName()) ;
    result->SetIsHide(annotation->GetIsHide()) ;
    result->SetRoughnessObtentionType(ToExchangePMIRoughnessObtentionType(annotation->GetRoughnessObtentionType())) ;
    result->SetRoughnessApplicabilityType(ToExchangePMIRoughnessApplicabilityType(annotation->GetRoughnessApplicabilityType())) ;
    
    for(auto f: annotation->GetRoughnessField())
    {
        result->AddRoughnessField(f) ;
    }

    
    return result ;
}

std::shared_ptr<Core::PMI::ExchangePMIAnnotation> ToExchangeAnnotation(const std::shared_ptr<InterOp::PMI::InterOpPMIAnnotation> & annotation){
    if(IS_InterOpPMIDimension(annotation)){
        return ToExchangePMIDimension(annotation)  ;
    }

    if(IS_InterOpGDT(annotation)){
        return ToExchangeGDT(annotation)  ;
    }

    if(IS_InterOpPMIDatumTarget(annotation)){
        return ToExchangePMIDatumTarget(annotation)  ;
    }

    if(IS_PMIInterOpDatum(annotation)){
        return ToExchangeDatum(annotation)  ;
    }

    if(IS_InterOpNote(annotation)){
        return ToExchangePMINote(annotation)  ;
    }

    if(IS_InterOpRoughness(annotation)){
        return ToExchangePMIRoughness(annotation)  ;
    }
    return nullptr ;
}

void ConvertInterOpPMI2ExchangePMI(
    const std::unordered_map<std::string,AMCAX::Exchange::InterOp::PMI::InterOpShapePMIInfos> &in,
    std::unordered_map<std::string,Core::PMI::ExchangeShapePMIInfos> &out
) 
{
    for (auto &p : in)
    {
        std::string key = p.first ;
        InterOp::PMI::InterOpShapePMIInfos infos = p.second ;
        std::vector<std::shared_ptr<InterOp::PMI::InterOpPMIAnnotation>>  annotationList = infos.GetPMIInfo() ;
        Core::PMI::ExchangeShapePMIInfos  exchangePMIInfos ;
        for(auto annotation : annotationList){
            auto exchangeAnnotaion = ToExchangeAnnotation(annotation) ;
            if (!exchangeAnnotaion)
            {
                continue;
            }
            
            exchangePMIInfos.AddPMIInfo(exchangeAnnotaion) ;
        }
        out.emplace(key,exchangePMIInfos) ;
    }
    
}

}

AMCAX_EXCHANGE_NAMESPACE_END